from common.decorators import catch_error
from app.product.category import service
from app.user.decorators import token_required
from common.responses import ok
from flask import g
from common.response_model import base_model, pagination_model
from common.request_parser import get_parser as base_get_parser
from flask_restplus import Resource, Namespace, fields, marshal, reqparse, Model
from app.product.category.model import Category
api = Namespace('category')

# ---------- model ----------
parent_model = Model('parent', {
    "id": fields.Integer(description='parent_id'),
    'name': fields.String(description='parent_name')
})
category_model = base_model.inherit('category_model', {
    "parent_id": fields.Integer(description='parent_id'),
    'parent': fields.Nested(parent_model, skip_none=True)
})
# category_model['parent'] = {
#     'id': fields.Integer(description='parent.id', attribute='parent.id'),
#     'name': fields.String(description='parent_name', attribute='parent.name')
# }
category_paginate_model = pagination_model.inherit('category_paginate_model', {
    "items": fields.Nested(category_model)
})

# ---------- create parser ----------
create_parser = reqparse.RequestParser()
create_parser.add_argument('name', type=str, required=True, help='名称')
create_parser.add_argument('short_name', type=str, help='名称拼音缩写，默认不用填写')
create_parser.add_argument('parent_id', type=int, help='父类别id')
create_parser.add_argument('notes', type=str, help='备注')
create_parser.add_argument('is_active', type=bool, choices=[True, False], help='是否启用')

# ---------- get parser ----------
get_parser = reqparse.RequestParser()
get_parser.add_argument('is_active', type=str, choices=["false", "true"], help='是否启用')
get_parser.add_argument('filter_category_id', type=int)

# get_parser.add_argument('parent_id', type=int, help='父类id')

# ---------- put parser ----------
batch_put_parser = reqparse.RequestParser()
batch_put_parser.add_argument('ids_list', type=int, action='append', required=True)
batch_put_parser.add_argument('is_active', type=bool, choices=[True, False], help='是否启用')

put_parser = create_parser.copy()
put_parser.replace_argument('name', type=str, help='名称')


# ---------- delete parser ----------
batch_delete_parser = reqparse.RequestParser()
batch_delete_parser.add_argument('ids_list', type=int, action='append', required=True)


class CategoriesResource(Resource):
    @catch_error
    @token_required
    @api.expect(create_parser)
    def post(self):
        """创建"""
        args = create_parser.parse_args()
        new_obj = Category.create(**args, commit=True)
        # new_obj = service.create(g.user_id, **args)
        return ok(data=marshal(new_obj, category_model),
                  message='create success')

    @catch_error
    @token_required
    @api.expect(get_parser)
    def get(self):
        """获取树列表"""
        args = get_parser.parse_args()
        filter_category_id = args.pop("filter_category_id")
        for key in list(args.keys()):
            if args.get(key) is None:
                del args[key]
        all_category = service.get_all(user_id=g.user_id, **args)
        all_category_json = marshal(all_category, category_model)
        # 过滤掉他自己的子类
        if filter_category_id:
            all_category_json = [category for category in all_category_json if category["id"] != filter_category_id]

        all_category_tree_json = service.category_list_to_tree_dict(all_category_json)
        return ok(data=all_category_tree_json,
                  message='get success')

    # 批量删除
    @catch_error
    @token_required
    @api.expect(batch_delete_parser)
    def delete(self):
        args = batch_delete_parser.parse_args()
        delete_ids = Category.hard_delete_many(ids=args.get("ids_list"), commit=True)
        # delete_ids = service.delete_many(g.user_id, args.get("ids_list"))
        return ok(
            data={
                'ids_list': delete_ids
            },
            message='delete success')

    # 批量修改
    @catch_error
    @token_required
    @api.expect(batch_put_parser)
    def put(self):
        args = batch_put_parser.parse_args()
        # 如果为空，则不要更新，删除None
        for key in list(args.keys()):
            if args.get(key) is None:
                del args[key]
        ids_list = Category.update_many(
            ids=args.pop("ids_list"),
            **args,
            commit=True
        )
        # update_ids_list = service.batch_update(g.user_id, args.pop("ids_list"), **args)

        return ok(
            data={
                'ids_list': ids_list
            },
            message='update success')


class CategoryResource(Resource):
    @catch_error
    @token_required
    def get(self, obj_id):
        """获取"""
        obj = Category.query.filter_by(id=obj_id).first()
        # obj = service.get(g.user_id, obj_id)
        return ok(data=marshal(obj, category_model),
                  message='get success')

    @catch_error
    @token_required
    @api.expect(put_parser)
    def put(self, obj_id):
        """更新"""
        args = put_parser.parse_args()
        for key in list(args.keys()):
            if args.get(key) is None:
                del args[key]

        obj = Category.query.filter_by(id=obj_id).first()
        obj.update(**args, commit=True)
        # obj = service.update(g.user_id, obj_id, **args)
        return ok(data=marshal(obj, category_model),
                  message='update success')

    @catch_error
    @token_required
    def delete(self, obj_id):
        """获取"""
        obj = Category.query.filter_by(id=obj_id).first()
        delete_id = obj.hard_delete(commit=True)
        # delete_id = service.delete(g.user_id, obj_id)
        return ok(
            data={
                'id': delete_id
            },
            message='delete success')


# --------- route ----------
api.add_resource(CategoriesResource, '/categories')
api.add_resource(CategoryResource, '/categories/<int:obj_id>')

# 注册 response 文档
api.models[category_model.name] = category_model
